﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using JScriptSuite.BrowserHost.Contracts;
using JScriptSuite.QA.Lib.System;
using JScriptSuite.QA.Lib;
using System.Text;
using JScriptSuite.Common;
using JScriptSuite.QA.Lib.Html;
using JScriptSuite.BrowserHost;
using System.Reflection;

namespace JScriptSuite.QA.App
{
    static class Program
    {
        readonly static string jsStartMethod = "Start";
        static LocalPageFactory pageFactory;
        static IBrowserHost host;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            string path = Path.GetDirectoryName(typeof(Program).Assembly.Location);
            path = Path.Combine(path, "pages");
            pageFactory = new LocalPageFactory(Path.Combine(path, "{0}.html"), Path.Combine(path, "{0}.js"));
            host = Host.CreateBrowserHost();
            ExecuteTests(TestSystem, TestHtml);
            host.Run();
        }

        static void TestSystem(Action next)
        {
            TestApp("System", SystemApp.AllTests, next);
        }

        
        static void TestHtml(Action next)
        {
            TestApp("Html", HtmlApp.AllTests, next);
        }

        static void ExecuteTests(params Action<Action>[] tests)
        {
            ExecuteTests(0, tests);
        }

        static void ExecuteTests(int index, Action<Action>[] tests)
        {
            Action nextStep = index != tests.Length - 1 ? delegate() { ExecuteTests(index + 1, tests); } : (Action)null;
            tests[index](nextStep);
        }
        
        static void TestApp(string page, Action<Action<JResultItem, Func<object, object>>> test, Action nextStep)
        {
            IPageHost pageHost = pageFactory.AddPage(host, page).Add(test, jsStartMethod);
            pageHost.Navigate(false, 
                0, 
                new Action<JResultItem, Func<object, object>>(delegate(JResultItem netResults, Func<object, object> netUnwrapper)
                {
                    ResultItem expected = ResultItem.Query(netResults, netUnwrapper);
                    pageHost.Navigate(true, 
                        0,
                        new Action<JResultItem, Func<object, object>>(delegate(JResultItem javascriptJResult, Func<object, object> jsUnwrapper)
                        {
                            ResultItem detected = ResultItem.Query(javascriptJResult, jsUnwrapper);
                            DifferenceRecorder recorder = new DifferenceRecorder();
                            recorder.AddDifferences(expected, detected);
                            string differences = recorder.Differences;
                            MessageBox.Show(
                                (
                                    string.IsNullOrEmpty(differences)
                                    ? "No dififerences have been detected between C# and Javascript version."
                                    : differences
                                ),
                                pageHost.Title);
                            if (nextStep != null)
                            {
                                nextStep();
                            }
                            else
                            {
                                // Application.Exit();
                            }
                        }));
                }));
        }
    }
}
